#include "demo08.h"

static thread_local Thread* t_thread = nullptr; //指向当前线程  
static thread_local std::string t_thread_name = "UNKNOW";   //当前的线程名称

Semaphore::Semaphore(uint32_t count) {
    if(sem_init(&m_semaphore, 0, count)) {
        throw std::logic_error("sem_init error");
    }
}

Semaphore::~Semaphore() {
    sem_destroy(&m_semaphore);
}

void Semaphore::wait() {
    //如果信号量的值大于零，sem_wait 会将其减一，然后线程可以继续执行并访问资源，如果信号量的值为零，则线程会在信号量上阻塞，直到信号量的值变为非零
    if(sem_wait(&m_semaphore)) { //运行线程访问公共资源 信号量减1
        throw std::logic_error("sem_wait error");
    }
}

void Semaphore::notify() {
    if(sem_post(&m_semaphore)) { //线程结束公共资源的访问 信号量加1
        throw std::logic_error("sem_post error");
    }
}

Thread::Thread(std::function<void()> cb, const std::string& name):m_cb(cb), m_name(name){
    if(name.empty()){
        m_name = "unknow";
    }

    int rt = pthread_create(&m_thread, nullptr, &Thread::run, this);
    if(rt){
        std::cout<< "pthread_create thread fail, rt=" << rt
            << " name=" << name << std::endl;
        throw std::logic_error("pthread_create error");
    }

    //构造未完成的时候等待...
    m_semaphore.wait(); //可以保证线程处于运行状态
}

//释放线程
Thread::~Thread(){
    // if(m_thread){
    //     pthread_detach(m_thread);
    // }
    m_thread = 0;
}

//获取当前线程
Thread* Thread::GetThis() {
    return t_thread;
}

//获取当前线程名字
const std::string& Thread::GetName() {
    return t_thread_name;
}

//设置当前线程名字
void Thread::SetName(const std::string& name) {
    if(t_thread) {
        t_thread->m_name = name;
    }
    t_thread_name = name;
}

//连接线程，用于阻塞
void Thread::join(){
    if(m_thread){
        int rt = pthread_join(m_thread, nullptr); //允许一个线程（通常是主线程）等待另一个线程（工作线程）完成其执行
        if(rt){
            std::cout<< "pthread_join thread fail, rt=" << rt
                << " name=" << m_name << std::endl;
            throw std::logic_error("pthread_join error");
        }
    }
}

void* Thread::run(void* arg){
    Thread* thread = (Thread*)arg;
    t_thread = thread;  //把线程赋值给他t_thread
    t_thread_name = thread->m_name;
    thread->m_id = sylar::GetThreadId();
    pthread_setname_np(pthread_self(), thread->m_name.substr(0,15).c_str()); //用于设置线程的名称

    std::function<void()> cb;
    cb.swap(thread->m_cb);
    //执行完成后要发起通知
    thread->m_semaphore.notify(); //公共资源访问结束 对信号量加1操作
    cb(); //执行回调函数
    return 0;

}

